package com.hontlong.boy.lucene;

import org.apache.log4j.Logger;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.ResultSetHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Index;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.LockObtainFailedException;

import com.hontlong.segment.analysis.MyAnalyzer;
import com.hontlong.segment.dictionary.Dictionary;

/**
 * ����lucene�Ľӿ�
 * 
 * @author zhaigy
 * @date Feb 22, 2008
 */
public final class Console {
	private static final int BATCH_SIZE = 1000;
	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger.getLogger(Console.class);

	static private void createIndex() {
		if (Console.logger.isDebugEnabled()) {
			Console.logger.debug("createIndex() - start");
		}

		final String curIdFile = "./lucene.curId.txt";
		final RandomAccessFile idFile = new Object() {
			public RandomAccessFile cal() {
				if (Console.logger.isDebugEnabled()) {
					Console.logger.debug("cal() - start");
				}

				try {
					final File f = new File(curIdFile);
					RandomAccessFile idFile = null;
					if (!f.exists()) {
						idFile = new RandomAccessFile(curIdFile, "rwd");
						idFile.writeBytes("" + (0));
					} else {
						idFile = new RandomAccessFile(curIdFile, "rwd");
					}

					if (Console.logger.isDebugEnabled()) {
						Console.logger.debug("cal() - end");
					}
					return idFile;
				} catch (FileNotFoundException e) {
					Console.logger.error("cal()", e);

					throw new RuntimeException(e);
				} catch (IOException e) {
					Console.logger.error("cal()", e);

					throw new RuntimeException(e);
				}
			}
		}.cal();
		final int curId = new Object() {
			public int cal() {
				if (Console.logger.isDebugEnabled()) {
					Console.logger.debug("cal() - start");
				}

				try {
					idFile.seek(0);
					String line = idFile.readLine();
					int returnint = Integer.parseInt(line);

					if (Console.logger.isDebugEnabled()) {
						Console.logger.debug("cal() - end");
					}
					return returnint;
				} catch (IOException e) {
					Console.logger.error("cal()", e);

					throw new RuntimeException(e);
				}
			}
		}.cal();

		final QueryRunner run = new QueryRunner();
		try {
			final Integer maxId;
			final Connection conn = DBConnectFactory.getDBConnection("boy");
			maxId = (Integer) run.query(conn, "select max(id) from t_ask",
					new ResultSetHandler() {
						@Override
						public Object handle(final ResultSet rs)
								throws SQLException {
							if (Console.logger.isDebugEnabled()) {
								Console.logger
										.debug("handle(ResultSet) - start");
							}

							if (rs.next()) {
								final Object returnObject = rs.getInt(1);
								if (Console.logger.isDebugEnabled()) {
									Console.logger
											.debug("handle(ResultSet) - end");
								}
								return returnObject;
							}

							if (Console.logger.isDebugEnabled()) {
								Console.logger.debug("handle(ResultSet) - end");
							}
							return 0;
						}
					});
			if (curId >= maxId) {
				if (Console.logger.isDebugEnabled()) {
					Console.logger.debug("createIndex() - end");
				}
				return;
			}

			final Analyzer analyzer = new MyAnalyzer(Dictionary.getInstance(
					"../segment/dic_h/dic_m.txt", "utf-8"));
			final IndexWriter iw = new IndexWriter("./index", analyzer);
			try {
				int num = 0;
				for (int i = curId + 1; i < maxId;) {
					final int start = i;
					final int end = i + Console.BATCH_SIZE - 1;// batch;
					Console.logger.info("id[" + start + "," + end + "]");
					final List<?> list = (List<?>) run
							.query(
									conn,
									"select id,askTitle,ask,`type` from t_ask where id between ? and ? ",
									new Object[] { start, end },
									new ArrayListHandler());
					try {
						for (final Object oo : list) {
							final Object[] os = (Object[]) oo;
							final int id = ((Number) os[0]).intValue();
							final String askTitle = (String) os[1];
							final String ask = (String) os[2];
							final String type = (String) os[3];
							final Document doc = new Document();
							Field f = new Field("id", "" + id, Store.YES,
									Index.NO);
							doc.add(f);
							if (askTitle != null) {
								f = new Field("askTitle", askTitle, Store.YES,
										Index.TOKENIZED);
								doc.add(f);
							}
							if (ask != null) {
								f = new Field("ask", ask, Store.YES,
										Index.TOKENIZED);
								doc.add(f);
							}
							if (type != null) {
								f = new Field("type", type, Store.YES, Index.NO);
								doc.add(f);
							}
							iw.addDocument(doc);
							++num;
							if (num % 1000 == 0) {
								Console.logger.info("already " + num);
							}
						}
					} finally {
						idFile.seek(0);
						idFile.writeBytes("" + end);
						Console.logger.info("total " + num);
					}
					i = end;
				}
				iw.optimize();
			} finally {
				iw.close();
			}
		} catch (final SQLException e) {
			Console.logger.error("createIndex()", e);

			throw new RuntimeException(e);
		} catch (final CorruptIndexException e) {
			Console.logger.error("createIndex()", e);

			throw new RuntimeException(e);
		} catch (final LockObtainFailedException e) {
			Console.logger.error("createIndex()", e);

			throw new RuntimeException(e);
		} catch (final IOException e) {
			Console.logger.error("createIndex()", e);

			throw new RuntimeException(e);
		}

		if (Console.logger.isDebugEnabled()) {
			Console.logger.debug("createIndex() - end");
		}
	}

	/**
	 * @param args
	 */
	public static void main(final String[] args) {
		if (Console.logger.isDebugEnabled()) {
			Console.logger.debug("main(String[]) - start");
		}

		try {
			Console.createIndex();
		} catch (final Throwable t) {
			Console.logger.error("main(String[])", t);

			Console.logger.error("", t);
		}

		if (Console.logger.isDebugEnabled()) {
			Console.logger.debug("main(String[]) - end");
		}
	}

}
